unit SimCell;

interface
uses
  Graphics,StdCtrls;

type
  PortName = (North,West,South,East);

  tCell_Sim = class
                private
//                  isdirty : boolean;
                  _code   : array[0..15] of byte;
                  _input  : array[PortName] of Boolean;
                  _output : array[PortName] of Boolean;
                  _OutFlag: array[PortName] of TCheckbox;
                  _OutBox : array[PortName] of TCheckbox;
                public
                  procedure  clear;
                  procedure  setinput(p : PortName; NewState : Boolean);
                  procedure  compute;
                  procedure  setprogram(s : string);
                  procedure  setflag(p : Portname; Box : Tcheckbox);
              end;



implementation

Procedure tCell_Sim.Clear;
var
  i : byte;
  p : portname;
begin
  for i := 0 to 15 do
    _code[i] := 0;

  for p := North to East do
  begin
    _Input[p] := false;
    _Output[p] := false;
    _OutFlag[p] := nil;
    _OutBox[p] := nil;
  end;
end;

procedure tCell_Sim.setinput(p : PortName; NewState : Boolean);
begin
  _Input[p] := NewState;
  compute;
end;

procedure tCell_Sim.compute;
var
  FlagColor : Array[Boolean] of tColor;
  InputIndex : Byte;
  OutputVal  : Byte;
  p          : portname;
begin
  FlagColor[false] := clBtnFace;
  FlagColor[true]  := clRed;
  InputIndex := 0;
  If _Input[North]     then Inc(InputIndex,8);
  If _Input[West]      then Inc(InputIndex,4);
  If _Input[South]     then Inc(InputIndex,2);
  If _Input[East]      then Inc(InputIndex);

  OutputVal := _Code[InputIndex];  // actual lookup

  _Output[North] :=  (OutputVal AND 8) <> 0;
  _Output[West]  :=  (OutputVal AND 4) <> 0;
  _Output[South] :=  (OutputVal AND 2) <> 0;
  _Output[East]  :=  (OutputVal AND 1) <> 0;

  for p := North to East do
  begin
    if (_OutFlag[p] <> nil) then
    begin
      if _output[p] then
        _OutFlag[p].Color := clRed
      else
        _OutFlag[p].Color := clBtnFace;
    end;
  end;
end;

procedure tCell_Sim.setprogram(S : String);
const
  hexstr : String = '123456789abcdef';
var
  i,x : byte;
  sub : string;
begin
  S := S + '0000000000000000';   // make sure its long enough
  for i := 0 to 15 do
  begin
    sub := s[i+1];
    x := pos(sub,hexstr);     // not found is a zero, so we don't have to subtract
    _code[i] := x;
  end;
  compute;
end;

procedure  tCell_Sim.setflag(p : Portname; Box : Tcheckbox);
begin
  _OutFlag[p] := Box;
  compute;
end;

end.
